package com.louis.iread.net;

import android.util.Log;

import com.android.databinding.library.baseAdapters.BR;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInput;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by louis on 2016/11/11.
 */

public class HttpUtil {

    private static final int MAX_CHECK_LINE = 200;
    public static String getStringFromUrlImpl(String urlStr, String userAgent, String refer, Map<String, String> headers) throws MalformedURLException, IOException {

        URL url = new URL(urlStr);
        URL referUrl = new URL(refer);
        if (url.getHost().equals(referUrl.getHost())) {
            if (!url.getProtocol().equals(referUrl.getProtocol())) {
                urlStr = urlStr.replace(url.getProtocol(), referUrl.getProtocol());
            }
        }

        InputStream inputStream = null;
        HttpURLConnection conn = null;
        try {
            URL newUrl = new URL(urlStr);
            conn = (HttpURLConnection) newUrl.openConnection();
            conn.setDoInput(true);
            conn.setRequestMethod("GET");
            conn.setRequestProperty("User-Agent", userAgent);
            conn.setRequestProperty("Referer", refer);
            conn.setRequestProperty("Connection", "keep-alive");
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            conn.setConnectTimeout(5 * 1000);
            conn.setReadTimeout(10 * 1000);
            conn.setInstanceFollowRedirects(true);
            conn.connect();

            if (conn.getResponseCode() == 200) {
                inputStream = conn.getInputStream();
                if (inputStream == null) {
                    return null;
                }
                String charset = "utf8";
                byte[] content = getBytesByInputStream(inputStream);
                String contentType = conn.getHeaderField("Content-Type");
                if (contentType.contains("charset")) {
                    int pos = contentType.indexOf("=");
                    charset = contentType.substring(pos).trim();
                } else {
                    String c = new String(content, "utf8");
//                Log.i("HttpUtil", c);
                    charset = checkEncoding(content);
                }
                String html = new String(content, charset);
                if (inputStream != null) {
                    inputStream.close();
                }
                if (conn != null) {
                    conn.disconnect();
                }

                return html;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (inputStream != null) {
                inputStream.close();
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }

    public static String getStringFromUrl(String urlStr, String userAgent, String refer,  int retryTimes, Map<String, String> headers) throws MalformedURLException, IOException {
        for (int i = 0; i < retryTimes; i++) {
            String html = getStringFromUrlImpl(urlStr, userAgent, refer, headers);
            if (html != null && html.length() > 0) {
                return html;
            }
        }
        return null;
    }

    public static String getStringFromUrl(String urlStr, String userAgent, String refer, Map<String, String> headers) throws MalformedURLException, IOException {
        return getStringFromUrl(urlStr, userAgent, refer,  3, headers);
    }

    public static String checkEncoding(byte[] content) {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content)));
        String charset = "utf8";
        int maxLineNum = MAX_CHECK_LINE;
        try {
            while (maxLineNum >= 0) {
                maxLineNum--;
                String line = bufferedReader.readLine();
                if (line.indexOf("meta") != -1) {
                    if (line.indexOf("charset") != -1) {
                        if (line.indexOf("utf8") != -1 || line.indexOf("utf-8") != -1 || line.indexOf("UTF-8") != -1) {
                            Log.i("HttpUril", line);
                            charset = "utf8";
                        } else if (line.indexOf("GBK") != -1 || line.indexOf("gbk") != -1 ||
                                line.indexOf("GB2312") != -1 || line.indexOf("gb2312") != -1 ||
                                line.indexOf("gb18030") != -1 || line.indexOf("GB18030") != -1) {
                            charset = "GB18030";
                        } else {
                            charset = "utf8";
                        }
                        break;
                    }
                }
            }
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return charset;
    }

    //从InputStream中读取数据，转换成byte数组，最后关闭InputStream
    private static byte[] getBytesByInputStream(InputStream is) {
        byte[] bytes = null;
        BufferedInputStream bis = new BufferedInputStream(is);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(baos);
        byte[] buffer = new byte[1024 * 8];
        int length = 0;
        try {
            while ((length = bis.read(buffer)) > 0) {
                bos.write(buffer, 0, length);
            }
            bos.flush();
            bytes = baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return bytes;
    }

    public static String getStringByOk(String url, Map<String, String> headers) {
        OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
        Headers.Builder builder = new Headers.Builder();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }
        Request request = new Request.Builder().url(url).headers(builder.build()).get().build();
        Call call = client.newCall(request);
        try {
            Response response = call.execute();
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
